package com.opNaga.bpmn;

import com.opNaga.bpmn.actions.build.Run;
import com.opNaga.bpmn.actions.edit.Copy;
import com.opNaga.bpmn.actions.edit.Cut;
import com.opNaga.bpmn.actions.edit.Delete;
import com.opNaga.bpmn.actions.edit.Paste;
import com.opNaga.bpmn.actions.history.Redo;
import com.opNaga.bpmn.actions.history.Undo;
import com.opNaga.bpmn.actions.io.Open;
import com.opNaga.bpmn.actions.io.Save;
import com.opNaga.bpmn.actions.view.FitContent;
import com.opNaga.bpmn.actions.view.ResetZoom;
import com.opNaga.bpmn.actions.view.Zoom;
import com.opNaga.bpmn.panel.BPMPPanel;
import com.opNaga.bpmn.panel.WorkFlowPanel;
import y.view.Graph2DView;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;

public class BPMPMain {
  private static Dimension SCREEN_SIZE = Toolkit.getDefaultToolkit().getScreenSize();
  private static final String RESOURCE_PATH = "./resource/ide/image";
  private JPanel contentPane;
  private InputMap inputMap;
  private ActionMap actionMap;
  private BpmnEdLayoutModule layoutOptions = new BpmnEdLayoutModule();
  private int usedLayout = BpmnEdLayoutModule.LAYOUT_FULL;
  private JComponent workFlowPanel;
  private JComponent abilityPanel;
  private JComponent networkPanel;
  private JComponent hierarchyPanel;
  private JTabbedPane tabbedPane;

  public BPMPMain() {
    contentPane = new JPanel();
    contentPane.setLayout(new BorderLayout());
    contentPane.setPreferredSize(new Dimension((int) (0.9 * SCREEN_SIZE.width), (int) (0.9 * SCREEN_SIZE.height)));
    actionMap = contentPane.getActionMap();
    inputMap = contentPane.getInputMap();

    workFlowPanel = new WorkFlowPanel();
    abilityPanel = new WorkFlowPanel();
    networkPanel = new WorkFlowPanel();
    hierarchyPanel = new WorkFlowPanel();

    tabbedPane = new JTabbedPane();
    tabbedPane.addTab("Work Flow", workFlowPanel);
    tabbedPane.addTab("Ability", abilityPanel);
    tabbedPane.addTab("Network", networkPanel);
    tabbedPane.addTab("Hierarchy", hierarchyPanel);
    contentPane.add(tabbedPane, BorderLayout.CENTER);
    tabbedPane.setInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
    tabbedPane.setActionMap(actionMap);

    JToolBar jtb = createToolBar();
    if(jtb != null) {
      contentPane.add(jtb, BorderLayout.NORTH);
    }
  }

  JToolBar createToolBar() {
    JToolBar toolBar = new JToolBar();
    Dimension separatorDimension = new Dimension((int) (SCREEN_SIZE.height * 0.02), (int) (SCREEN_SIZE.height * 0.05));
    Dimension buttonDimension = new Dimension((int) (SCREEN_SIZE.height * 0.05), (int) (SCREEN_SIZE.height * 0.05));
    toolBar.setFloatable(false);

    // io functions
    JButton openButton = new JButton();
    openButton.setAction(new Open(tabbedPane));
    openButton.setPreferredSize(buttonDimension);
    Image openImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/open.png");
    openButton.setIcon(new ImageIcon(openImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    openButton.setToolTipText("Open File");
    openButton.setBorderPainted(false);
    toolBar.add(openButton);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.META_DOWN_MASK), "OPEN");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_DOWN_MASK), "OPEN");
    actionMap.put("OPEN", openButton.getAction());

    JButton saveButton = new JButton();
    saveButton.setAction(new Save(tabbedPane));
    saveButton.setPreferredSize(buttonDimension);
    Image saveImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/save.png");
    saveButton.setIcon(new ImageIcon(saveImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    saveButton.setToolTipText("Save File");
    saveButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.META_DOWN_MASK), "SAVE");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_DOWN_MASK), "SAVE");
    actionMap.put("SAVE", saveButton.getAction());
    toolBar.add(saveButton);

    // zoom functions
    toolBar.addSeparator(separatorDimension);

    JButton zoomInButton = new JButton();
    zoomInButton.setAction(new Zoom(tabbedPane, 1.25));
    zoomInButton.setPreferredSize(buttonDimension);
    Image zoomInImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/zoomIn.png");
    zoomInButton.setIcon(new ImageIcon(zoomInImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    zoomInButton.setToolTipText("Zoom In");
    zoomInButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.META_DOWN_MASK), "ZOOM_IN");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_EQUALS, KeyEvent.CTRL_DOWN_MASK), "ZOOM_IN");
    actionMap.put("ZOOM_IN", zoomInButton.getAction());
    toolBar.add(zoomInButton);

    JButton zoomOutButton = new JButton();
    zoomOutButton.setAction(new Zoom(tabbedPane, 0.8));
    zoomOutButton.setPreferredSize(buttonDimension);
    Image zoomOutImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/zoomOut.png");
    zoomOutButton.setIcon(new ImageIcon(zoomOutImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    zoomOutButton.setToolTipText("Zoom Out");
    zoomOutButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, KeyEvent.META_DOWN_MASK), "ZOOM_OUT");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, KeyEvent.CTRL_DOWN_MASK), "ZOOM_OUT");
    actionMap.put("ZOOM_OUT", zoomOutButton.getAction());
    toolBar.add(zoomOutButton);

    JButton fitContentButton = new JButton();
    fitContentButton.setAction(new FitContent(tabbedPane));
    fitContentButton.setPreferredSize(buttonDimension);
    Image fitContentImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/fitContent.png");
    fitContentButton.setIcon(new ImageIcon(fitContentImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    fitContentButton.setToolTipText("Fit Content");
    fitContentButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, KeyEvent.META_DOWN_MASK), "FIT_CONTENT");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_1, KeyEvent.CTRL_DOWN_MASK), "FIT_CONTENT");
    actionMap.put("FIT_CONTENT", fitContentButton.getAction());
    toolBar.add(fitContentButton);

    JButton resetZoomButton = new JButton();
    resetZoomButton.setAction(new ResetZoom(tabbedPane));
    resetZoomButton.setPreferredSize(buttonDimension);
    Image resetZoomImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/resetZoom.png");
    resetZoomButton.setIcon(new ImageIcon(resetZoomImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    resetZoomButton.setToolTipText("Reset Zoom");
    resetZoomButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.META_DOWN_MASK), "RESET_ZOOM");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_2, KeyEvent.CTRL_DOWN_MASK), "RESET_ZOOM");
    actionMap.put("RESET_ZOOM", resetZoomButton.getAction());
    toolBar.add(resetZoomButton);

    // edit
    toolBar.addSeparator(separatorDimension);

    JButton cutButton = new JButton();
    cutButton.setAction(new Cut(tabbedPane));
    cutButton.setPreferredSize(buttonDimension);
    Image cutImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/cut.png");
    cutButton.setIcon(new ImageIcon(cutImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    cutButton.setToolTipText("Cut");
    cutButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.META_DOWN_MASK), "CUT");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK), "CUT");
    actionMap.put("CUT", cutButton.getAction());
    toolBar.add(cutButton);

    JButton copyButton = new JButton();
    copyButton.setAction(new Copy(tabbedPane));
    copyButton.setPreferredSize(buttonDimension);
    Image copyImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/copy.png");
    copyButton.setIcon(new ImageIcon(copyImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    copyButton.setToolTipText("Copy");
    copyButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.META_DOWN_MASK), "COPY");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_DOWN_MASK), "COPY");
    actionMap.put("COPY", copyButton.getAction());
    toolBar.add(copyButton);

    JButton pasteButton = new JButton();
    pasteButton.setAction(new Paste(tabbedPane));
    pasteButton.setPreferredSize(buttonDimension);
    Image pasteImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/paste.png");
    pasteButton.setIcon(new ImageIcon(pasteImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    pasteButton.setToolTipText("Paste");
    pasteButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.META_DOWN_MASK), "PASTE");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_DOWN_MASK), "PASTE");
    actionMap.put("PASTE", pasteButton.getAction());
    toolBar.add(pasteButton);

    JButton deleteButton = new JButton();
    deleteButton.setAction(new Delete(tabbedPane));
    deleteButton.setPreferredSize(buttonDimension);
    Image deleteImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/delete.png");
    deleteButton.setIcon(new ImageIcon(deleteImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    deleteButton.setToolTipText("Delete");
    deleteButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.META_DOWN_MASK), "DELETE");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, KeyEvent.CTRL_DOWN_MASK), "DELETE");
    inputMap.put(KeyStroke.getKeyStroke((char) KeyEvent.VK_BACK_SPACE), "DELETE");
    inputMap.put(KeyStroke.getKeyStroke((char) KeyEvent.VK_DELETE), "DELETE");
    actionMap.put("DELETE", deleteButton.getAction());
    toolBar.add(deleteButton);

    // undo
    toolBar.addSeparator(separatorDimension);

    JButton undoButton = new JButton();
    undoButton.setAction(new Undo(tabbedPane));
    undoButton.setPreferredSize(buttonDimension);
    Image undoImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/undo.png");
    undoButton.setIcon(new ImageIcon(undoImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    undoButton.setToolTipText("Undo");
    undoButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.META_DOWN_MASK), "UNDO");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK), "UNDO");
    actionMap.put("UNDO", undoButton.getAction());
    toolBar.add(undoButton);

    JButton redoButton = new JButton();
    redoButton.setAction(new Redo(tabbedPane));
    redoButton.setPreferredSize(buttonDimension);
    Image redoImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/redo.png");
    redoButton.setIcon(new ImageIcon(redoImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    redoButton.setToolTipText("Redo");
    redoButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.META_DOWN_MASK & KeyEvent.SHIFT_DOWN_MASK), "REDO");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK & KeyEvent.SHIFT_DOWN_MASK), "REDO");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.META_DOWN_MASK), "REDO");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_Y, KeyEvent.CTRL_DOWN_MASK), "REDO");
    actionMap.put("REDO", redoButton.getAction());
    toolBar.add(redoButton);

    // build
    toolBar.addSeparator(separatorDimension);
    JButton runButton = new JButton();
    runButton.setAction(new Run(tabbedPane));
    runButton.setPreferredSize(buttonDimension);
    Image runImage = Toolkit.getDefaultToolkit().getImage(RESOURCE_PATH + "/run.png");
    runButton.setIcon(new ImageIcon(runImage.getScaledInstance(buttonDimension.width, buttonDimension.height, Image.SCALE_SMOOTH)));
    runButton.setToolTipText("Run");
    runButton.setBorderPainted(false);
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.META_DOWN_MASK), "RUN");
    inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK), "RUN");
    actionMap.put("RUN", runButton.getAction());
    toolBar.add(runButton);

        //    toolBar.addSeparator();
    //    toolBar.add(createOrthoModeToggleButton());
    //    toolBar.add(createSnapModeToggleButton());
    //    toolBar.add(createGridModeToggleButton());

    //    toolBar.addSeparator();
    //    JPanel layoutControls = new JPanel(new FlowLayout(FlowLayout.LEADING));
    //    layoutControls.add(new LayoutSection("Layout"));
    //    toolBar.add(layoutControls);

    int tabNumber = tabbedPane.getTabCount();
    for(int t = 0; t < tabNumber; t++) {
      BPMPPanel bpmpPanel = (BPMPPanel) tabbedPane.getComponentAt(t);
      Graph2DView view = bpmpPanel.getView();
      view.setInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
      view.setActionMap(actionMap);
    }
    toolBar.setInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);
    toolBar.setActionMap(actionMap);
    return toolBar;
  }

  //  JComponent createOrthoModeToggleButton() {
  //    final JToggleButton ortogonalButton = new JToggleButton("", true);
  //    setIcon(ortogonalButton, RESOURCE_PATH + "/orthogonal_edit_mode.png");
  //    ortogonalButton.setToolTipText("Orthogonal Mode");
  //    ortogonalButton.addChangeListener(new ChangeListener() {
  //      public void stateChanged(ChangeEvent e) {
  //        view.setOrthogonalEdgeCreationEnabled(ortogonalButton.isSelected());
  //      }
  //    });
  //
  //    return ortogonalButton;
  //  }
  //
  //  JComponent createSnapModeToggleButton() {
  //    //For Snapping Mode
  //    final JToggleButton snapModeButton = new JToggleButton("", true);
  //    setIcon(snapModeButton, RESOURCE_PATH + "/snap_lines.png");
  //    snapModeButton.setToolTipText("Snap Mode");
  //
  //    snapModeButton.addChangeListener(new ChangeListener() {
  //      public void stateChanged(ChangeEvent e) {
  //        //Snapping for edit mode
  //        view.setSnappingEnabled(snapModeButton.isSelected());
  //      }
  //    });
  //    return snapModeButton;
  //  }
  //
  //  JComponent createGridModeToggleButton() {
  //    //For Grid Mode
  //    final JToggleButton gridModeButton = new JToggleButton();
  //    setIcon(gridModeButton, RESOURCE_PATH + "/grid.png");
  //    gridModeButton.setToolTipText("Grid");
  //    gridModeButton.addChangeListener(new ChangeListener() {
  //      public void stateChanged(ChangeEvent e) {
  //        view.setGridEnabled(gridModeButton.isSelected());
  //      }
  //    });
  //    return gridModeButton;
  //  }

  void start(String title) {
    JFrame frame = new JFrame(title);
    JOptionPane.setRootFrame(frame);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.addContentTo(frame.getRootPane());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }

  void addContentTo(final JRootPane rootPane) {
    rootPane.setContentPane(contentPane);
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        initLnF();
        final BPMPMain editor = new BPMPMain();
        editor.start("BPMN Editor");
      }
    });
  }

  static void initLnF() {
    try {
      if(!"com.sun.java.swing.plaf.motif.MotifLookAndFeel".equals(UIManager.getSystemLookAndFeelClassName()) && !("com" + ".sun.java.swing.plaf.gtk.GTKLookAndFeel").equals(UIManager.getSystemLookAndFeelClassName()) &&
          !UIManager.getSystemLookAndFeelClassName().equals(UIManager.getLookAndFeel().getClass().getName())) {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
      }
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  //  class LayoutSection extends JPanel {
  //    JRadioButton fullB;
  //    JRadioButton partialB;
  //    JRadioButton incrementalB;
  //    JRadioButton sketchB;
  //
  //    LayoutSection(String title) {
  //      super(new GridBagLayout());
  //      GridBagConstraints gbc = new GridBagConstraints();
  //      Insets none = gbc.insets;
  //      gbc.fill = GridBagConstraints.VERTICAL;
  //      gbc.gridy = 0;
  //      gbc.weightx = 0;
  //      gbc.anchor = GridBagConstraints.NORTHWEST;
  //
  //      gbc.insets = new Insets(0, 0, 0, 5);
  //      this.add(new JLabel(title + ":"), gbc);
  //
  //      final ButtonGroup bg = new ButtonGroup();
  //
  //      fullB = new JRadioButton("Full");
  //      partialB = new JRadioButton("Selected Edges");
  //      incrementalB = new JRadioButton("Incremental");
  //      sketchB = new JRadioButton("Sketch");
  //      fullB.setSelected(true);
  //
  //      ActionListener rl = new ActionListener() {
  //        public void actionPerformed(ActionEvent ev) {
  //          ButtonModel bm = bg.getSelection();
  //          if(bm == partialB.getModel()) {
  //            usedLayout = BpmnEdLayoutModule.LAYOUT_SELECTED_EDGES;
  //          } else if(bm == sketchB.getModel()) {
  //            usedLayout = BpmnEdLayoutModule.LAYOUT_SKETCH;
  //          } else if(bm == incrementalB.getModel()) {
  //            usedLayout = BpmnEdLayoutModule.LAYOUT_INCREMENTAL;
  //          } else {
  //            usedLayout = BpmnEdLayoutModule.LAYOUT_FULL;
  //          }
  //        }
  //      };
  //
  //      gbc.insets = none;
  //      addButton(fullB, bg, rl, gbc);
  //      addButton(partialB, bg, rl, gbc);
  //      addButton(incrementalB, bg, rl, gbc);
  //      addButton(sketchB, bg, rl, gbc);
  //
  //      JButton layoutOptionButton = new JButton(new BpmnLayoutOptionAction());
  //      gbc.insets = new Insets(0, 5, 0, 0);
  //      this.add(layoutOptionButton, gbc);
  //
  //      JButton layoutButton = new JButton(new BpmnLayoutAction());
  //      gbc.insets = none;
  //      this.add(layoutButton, gbc);
  //    }
  //
  //    void addButton(JRadioButton b, ButtonGroup bg, ActionListener rl, GridBagConstraints gbc) {
  //      bg.add(b);
  //      this.add(b, gbc);
  //      b.addActionListener(rl);
  //    }
  //  }

  //  private class BpmnLayoutAction extends AbstractAction {
  //    BpmnLayoutAction() {
  //      super("Execute");
  //    }
  //
  //    public void actionPerformed(ActionEvent e) {
  //      Graph2D graph = view.getGraph2D();
  //      BpmnLayoutConfigurator configurator = new BpmnLayoutConfigurator();
  //      configurator.prepareAll(graph);
  //      layoutOptions.start(graph, usedLayout);
  //      configurator.restoreAll(graph);
  //      view.fitContent();
  //    }
  //  }
  //
  //  private class BpmnLayoutOptionAction extends AbstractAction {
  //    BpmnLayoutOptionAction() {
  //      super("Options...");
  //    }
  //
  //    public void actionPerformed(ActionEvent e) {
  //      OptionHandler oh = layoutOptions.getOptionHandler();
  //      oh.showEditor();
  //    }
  //  }
}

